package com.bafa.objects;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.TreeMap;
import java.util.TreeSet;

import com.bafa.dbcache.LeagueCache;
import com.bafa.objects.schema.ObjectFactory;
import com.bafa.objects.schema.Record;
import com.bafa.services.RetrieveServices;
import com.bafa.util.comparators.ScoreByBiggestLossComparator;
import com.bafa.util.comparators.ScoreByBiggestWinComparator;
import com.bafa.util.comparators.ScoreByMostScoredComparator;
import com.bafa.util.comparators.TopScorerComparator;

public class TeamStats implements Serializable{

	private int[] recordCleanSheets = new int[2];
	private int allTimeCleanSheets;
	
	private int[] recordGoalsScored = new int[2];;
	private int allTimeGoalsScored;
	
	private int[] recordGoalsConceded = new int[2];;
	private int allTimeGoalsConceded;
	
	private int[] recordLeaguePosition= new int[2];;
	
	private Scorer recordGoalScorer;
	
	private int[] recordPoints= new int[2];
	private int allTimePoints;
	
	private int totalGamesPlayed;
	private int goalsScoredPerGame;
	private int goalsConcededPerGame;
	
	private int totalGamesWon;
	private int totalGamesLost;
	private int totalGamesDrawn;
	
	//private TreeSet allTimeScorers = new TreeSet(new TopScorerComparator());
	private TreeMap<String,Scorer> allTimeScorers = new TreeMap();
	
	private TreeMap awards = new TreeMap();
	
	private TreeMap seasons = new TreeMap();
	
	//private TreeMap allMatches = new TreeMap();
	
	private Score biggestWinScore;
	private Score biggestLossScore;
	private Score mostScored;

	public TeamStats(com.bafa.objects.schema.TeamStats teamStats){
		for(int i=0;i<teamStats.getTeamSeason().size();i++){
			this.addTeamSeason(teamStats.getTeamSeason().get(i).getSeasonId(),new TeamSeason(teamStats.getTeamSeason().get(i)));
		}
		
		this.setRecordCleanSheets(teamStats.getRecordCleanSheets().getNumber(), teamStats.getRecordCleanSheets().getSeasonId());
		this.setRecordGoalsScored(teamStats.getRecordGoalsScored().getNumber(), teamStats.getRecordGoalsScored().getSeasonId());
		this.setRecordGoalsConceded(teamStats.getRecordGoalsConceded().getNumber(), teamStats.getRecordGoalsConceded().getSeasonId());
		if(teamStats.getRecordLeaguePosition()!=null)this.setRecordLeaguePosition(teamStats.getRecordLeaguePosition().getNumber(), teamStats.getRecordLeaguePosition().getSeasonId());
		this.setRecordGoalScorer(new Scorer(teamStats.getRecordGoalScorer()));
		this.setAllTimeCleanSheets(teamStats.getCleanSheets());
		this.setAllTimeGoalsConceded(teamStats.getGoalsConceded());
		this.setAllTimeGoalsScored(teamStats.getGoalsScored());
		this.setTotalGamesDrawn(teamStats.getGamesDrawn());
		this.setTotalGamesWon(teamStats.getGamesWon());
		this.setTotalGamesPlayed(teamStats.getGamesPlayed());
		this.setTotalGamesLost(teamStats.getGamesLost());
		
		for(int i=0;i<teamStats.getScorer().size();i++){
			this.addAllTimeScorer(new Scorer(teamStats.getScorer().get(i)));
		}
		
                if(teamStats.getBiggestWin().getID()>0)
                    biggestWinScore = new Score(teamStats.getBiggestWin());
                if(teamStats.getBiggestDefeat().getID()>0)
                    biggestLossScore = new Score(teamStats.getBiggestDefeat());
                if(teamStats.getMostScored().getID()>0)
                    mostScored = new Score(teamStats.getMostScored());
		//this.setAllTimePoints(teamStats.getP)
		
	}
	
	public TeamSeason getTeamSeason(int seasonId){
		return (TeamSeason)seasons.get(seasonId);
	}
	

	public int[] getRecordCleanSheets() {
		return recordCleanSheets;
	}

	public void setRecordCleanSheets(int recordCleanSheets, int seasonId) {
		this.recordCleanSheets[0] = recordCleanSheets;
		this.recordCleanSheets[1] = seasonId;
	}

	public int getAllTimeCleanSheets() {
		return allTimeCleanSheets;
	}

	public void setAllTimeCleanSheets(int allTimeCleanSheets) {
		this.allTimeCleanSheets = allTimeCleanSheets;
	}

	public int getAllTimeGoalsScored() {
		return allTimeGoalsScored;
	}

	public int[] getRecordGoalsScored() {
		return recordGoalsScored;
	}

	public void setAllTimeGoalsScored(int allTimeGoalsScored) {
		this.allTimeGoalsScored = allTimeGoalsScored;
	}

	public void setRecordGoalsScored(int recordGoalsScored, int seasonId) {
		this.recordGoalsScored[0] = recordGoalsScored;
		this.recordGoalsScored[1] = seasonId;
	}

	public int getAllTimeGoalsConceded() {
		return allTimeGoalsConceded;
	}

	public void setAllTimeGoalsConceded(int allTimeGoalsConceded) {
		this.allTimeGoalsConceded = allTimeGoalsConceded;
	}

	public int[] getRecordGoalsConceded() {
		return recordGoalsConceded;
	}

	public void setRecordGoalsConceded(int recordGoalsConceded, int seasonId) {
		this.recordGoalsConceded[0] = recordGoalsConceded;
		this.recordGoalsConceded[1] = seasonId;
	}

	public int getTotalGamesPlayed() {
		return totalGamesPlayed;
	}

	public void setTotalGamesPlayed(int totalGamesPlayed) {
		this.totalGamesPlayed = totalGamesPlayed;
	}

	public int getAllTimePoints() {
		return allTimePoints;
	}

	public float getGoalsConcededPerGame() {
		BigDecimal amount = new BigDecimal(allTimeGoalsConceded).setScale(2).divide(new BigDecimal(totalGamesPlayed).setScale(2),2,BigDecimal.ROUND_UP);
		return amount.floatValue();
	}

	public float getGoalsScoredPerGame() {
		BigDecimal amount = new BigDecimal(allTimeGoalsScored).setScale(2).divide(new BigDecimal(totalGamesPlayed).setScale(2),2,BigDecimal.ROUND_UP);
		return amount.floatValue();
	}

	public float percentageCleanSheets(){
                BigDecimal amount = new BigDecimal(0.0);
                if(totalGamesPlayed>0)
                    amount = new BigDecimal(allTimeCleanSheets).setScale(2).divide(new BigDecimal(totalGamesPlayed).setScale(2),2,BigDecimal.ROUND_UP).multiply(new BigDecimal(100));
		return amount.floatValue();
	}
	
	public float percentageWon(){
                BigDecimal amount = new BigDecimal(0.0);
                if(totalGamesPlayed>0)
                    amount = new BigDecimal(totalGamesWon).setScale(2).divide(new BigDecimal(totalGamesPlayed).setScale(2),2,BigDecimal.ROUND_UP).multiply(new BigDecimal(100));
		return amount.floatValue();
	}
	
	public int[] getRecordPoints() {
		return recordPoints;
	}

	public int getTotalGamesWon() {
		return totalGamesWon;
	}

	public void setTotalGamesWon(int totalGamesWon) {
		this.totalGamesWon = totalGamesWon;
	}

	public int getTotalGamesDrawn() {
		return totalGamesDrawn;
	}

	public void setTotalGamesDrawn(int toalGamesDrawn) {
		this.totalGamesDrawn = toalGamesDrawn;
	}

	public int getTotalGamesLost() {
		return totalGamesLost;
	}

	public void setTotalGamesLost(int totalGamesLost) {
		this.totalGamesLost = totalGamesLost;
	}

	public void setAllTimePoints(int allTimePoints) {
		this.allTimePoints = allTimePoints;
	}

	public void setGoalsConcededPerGame(int goalsConcededPerGame) {
		this.goalsConcededPerGame = goalsConcededPerGame;
	}

	public void setGoalsScoredPerGame(int goalsScoredPerGame) {
		this.goalsScoredPerGame = goalsScoredPerGame;
	}

	public void setRecordPoints(int recordPoints, int seasonId) {
		this.recordPoints[0] = recordPoints;
		this.recordPoints[1] = seasonId;
	}

	public int[] getRecordLeaguePosition() {
		return recordLeaguePosition;
	}

	public void setRecordLeaguePosition(int recordLeaguePosition, int seasonId) {
		this.recordLeaguePosition[0] = recordLeaguePosition;
		this.recordLeaguePosition[1] = seasonId;
	}

	public TeamAward[] awards(){
		return (TeamAward[])awards.values().toArray(new TeamAward[awards.size()]);
	}
	
	/*****************ADD METHODS****************/
	public void addAllTimeScorer(Scorer scorer){
		if(!scorer.getName().equalsIgnoreCase("o.g.")&&
				!scorer.getName().equalsIgnoreCase("own goal")&&
				!scorer.getName().equalsIgnoreCase("og"))
			allTimeScorers.put(scorer.getName(),scorer);
	}
	public void addTeamSeason(int seasonId,TeamSeason season){
		seasons.put(seasonId,season);
	}
	
	public void addAwards(int seasonId,TeamAward award){
		awards.put(seasonId,award);
	}
	
	public void addMatch(int matchId,Score match){
		//allMatches.put(matchId,match);
		addBiggestWin(match);
		addBiggestLoss(match);
		addMostScored(match);
	}
	/********************************************/


	public TreeSet getAllTimeScorers() {
		TreeSet set = new TreeSet(new TopScorerComparator());
		
		set.addAll(allTimeScorers.values());
		return set;
	}
	
	public Scorer getScorer(int index) {
		Scorer[] scorer = (Scorer[])getAllTimeScorers().toArray(new Scorer[getAllTimeScorers().size()]);
		return scorer[index];
	}
	public TeamSeason[] seasons(){
		return (TeamSeason[])seasons.values().toArray(new TeamSeason[seasons.size()]);
	}
	
	public Score getBiggestWin(){
		return biggestWinScore;
	}
	
	public Score getBiggestLoss(){
		return biggestLossScore;
	}
	
	public Score getMostScored(){
		return mostScored;
	}
	public Scorer getRecordGoalScorer() {
		return recordGoalScorer;
	}

	public void setRecordGoalScorer(Scorer scorer) {
		this.recordGoalScorer=scorer;
	}
	
	/***************Object Logic*******************/
	private void addBiggestWin(Score newScore){
		if(biggestWinScore!=null){
			int margin1 = biggestWinScore.getGoalsFor()- biggestWinScore.getGoalsAgainst();
			int margin2 = newScore.getGoalsFor()- newScore.getGoalsAgainst();
		
			if(margin1==margin2){
				if(biggestWinScore.getGoalsFor()<newScore.getGoalsFor())
					biggestWinScore=newScore;
				else if(biggestWinScore.getDate().after(newScore.getDate()))
					biggestWinScore=newScore;
				
			}else if(margin2>margin1){
				biggestWinScore = newScore;
			}
		}else{
			biggestWinScore = newScore;
		}
	}
	
	private void addBiggestLoss(Score newScore){
		if(biggestLossScore!=null){
			int margin1 = biggestLossScore.getGoalsAgainst()- biggestLossScore.getGoalsFor();
			int margin2 = newScore.getGoalsAgainst()- newScore.getGoalsFor();
		
			if(margin1==margin2){
				if(biggestLossScore.getGoalsAgainst()<newScore.getGoalsAgainst())
					biggestLossScore=newScore;
				else if(biggestLossScore.getDate().after(newScore.getDate()))
					biggestLossScore=newScore;
				
			}else if(margin2>margin1){
				biggestLossScore = newScore;
			}
		}else{
			biggestLossScore = newScore;
		}
	}
	
	private void addMostScored(Score newScore){
		if(mostScored!=null){
			
			if(mostScored.getGoalsFor()<newScore.getGoalsFor()){
				mostScored = newScore;
			}else if(mostScored.getGoalsFor()==newScore.getGoalsFor()){
				if(mostScored.getDate().after(newScore.getDate()))
					mostScored=newScore;
			}
		}else{
			mostScored = newScore;
		}
	}
	/**********************************************/

	public com.bafa.objects.schema.TeamStats mapTo(){
		ObjectFactory factory = new ObjectFactory();
		com.bafa.objects.schema.TeamStats stats = factory.createTeamStats();
		
		com.bafa.objects.schema.Record record = factory.createRecord();
		
		//Cleansheets
		record.setNumber(getRecordCleanSheets()[0]);
		record.setSeasonId(getRecordCleanSheets()[1]);
		stats.setRecordCleanSheets(record);
		// Cleansheets
		
		//Goals Scored
		record.setNumber(getRecordGoalsScored()[0]);
		record.setSeasonId(getRecordGoalsScored()[1]);
		stats.setRecordGoalsScored(record);
		//Goals Scored
		
		//Goals Conceded
		record.setNumber(getRecordGoalsConceded()[0]);
		record.setSeasonId(getRecordGoalsConceded()[1]);
		stats.setRecordGoalsConceded(record);
		//Goals Conceded
		
		//League Pos
		record.setNumber(getRecordLeaguePosition()[0]);
		record.setSeasonId(getRecordLeaguePosition()[1]);
		stats.setRecordLeaguePosition(record);
		//League Pos
		
		//Goal Scorer
		com.bafa.objects.schema.Scorer scorer = factory.createScorer();
		scorer.setGoals(getRecordGoalScorer().getGoals());
		scorer.setSeasonId(getRecordGoalScorer().getSeasonId());
		scorer.setName(getRecordGoalScorer().getName());
		scorer.setTeamId(getRecordGoalScorer().getTeamId());
		stats.setRecordGoalScorer(scorer);
		//Goal Scorer
		
		
		
		return stats;
	}

    public void setSeasons(TreeMap seasons) {
        this.seasons = seasons;
    }

    public TreeMap getSeasons() {
        return seasons;
    }
}
